package com.hfi.security.core.social.weixin.connect;

import com.hfi.security.core.social.weixin.api.Weixin;
import org.springframework.social.connect.ApiAdapter;
import org.springframework.social.connect.Connection;
import org.springframework.social.connect.ConnectionData;
import org.springframework.social.connect.support.OAuth2Connection;
import org.springframework.social.connect.support.OAuth2ConnectionFactory;
import org.springframework.social.oauth2.AccessGrant;
import org.springframework.social.oauth2.OAuth2ServiceProvider;

/**
 * @author ChangLiang
 * @date 2019/8/23
 */
public class WeixinConnectionFactory extends OAuth2ConnectionFactory<Weixin> {

    /**
     * 并没有使用父类的构造函数 super(providerId, serviceProvider, apiAdapter)
     * @param providerId
     * @param appId
     * @param appSecret
     */
    public WeixinConnectionFactory(String providerId,String appId, String appSecret) {
        super(providerId, new WeixinServiceProvider(appId,appSecret), new WeixinAdapter());
    }

    /**
     * 用于从返回的{@link AccessGrant}中提取providerUserId
     * 由于微信的openId是和accessToken一起返回的，所以在这里直接根据获取accessToken的结果取到providerUserId(openid)
     * 不用像QQ那样 通过QQImpl构造函数 根据accessToken来获取openId
     * @param accessGrant
     * @return
     */
    @Override
    protected String extractProviderUserId(AccessGrant accessGrant) {
        if (accessGrant instanceof WeixinAccessGrant) {
            return ((WeixinAccessGrant) accessGrant).getOpenId();
        }
        return null;
    }

    @Override
    public Connection<Weixin> createConnection(AccessGrant accessGrant) {
        return new OAuth2Connection<Weixin>(getProviderId(), extractProviderUserId(accessGrant),
                accessGrant.getAccessToken(),
                accessGrant.getRefreshToken(), accessGrant.getExpireTime(), (OAuth2ServiceProvider<Weixin>) getServiceProvider(),
                getWeixinAdapter(extractProviderUserId(accessGrant)));
    }

    @Override
    public Connection<Weixin> createConnection(ConnectionData data) {
        return new OAuth2Connection<Weixin>(data, (OAuth2ServiceProvider<Weixin>) getServiceProvider(),
                getWeixinAdapter(data.getProviderUserId()));
    }

    /**
     * 在默认实现里面，其返回的apiAdapter是同一个实例
     * 也就是说所有的OAuth2Connection拿到的都是同一个apiAdapter
     * 但在WeixinAdapter中，由于有一个openId字段
     * 那么其应该是多例的
     * 所以其处理过程应该是 根据用户返回的access_token响应中包含的openid
     * 针对每一个oauthConnection，都new了一个新的WeixinAdapter
     * 这里是整个微信登录与qq登录最大区别的地方
     * @param providerUserId
     * @return
     */
    private ApiAdapter<Weixin> getWeixinAdapter(String providerUserId) {
        return new WeixinAdapter(providerUserId);
    }

}
